import aiohttp
from flask import Flask
from prometheus_client import CollectorRegistry, Gauge
from gevent import pywsgi
from logging.config import dictConfig
import time
import yaml
import os
import asyncio
from aiohttp import ClientSession, ClientConnectorError

dictConfig({
    'version': 1,
    'formatters': {'default': {
        'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s',
    }},
    'handlers': {'wsgi': {
        'class': 'logging.StreamHandler',
        'stream': 'ext://flask.logging.wsgi_errors_stream',
        'formatter': 'default'
    }},
    'root': {
        'level': 'DEBUG',
        'handlers': ['wsgi']
    }
})

app = Flask(__name__)

REGISTRY = CollectorRegistry()
GAUGE_STATUS_CODE = Gauge('api_status_code', '返回API请求状态码',
                          labelnames=['url', 'alias', 'type', 'match', 'group'], registry=REGISTRY)
GAUGE_REQUEST_TIME = Gauge('url_request_time', '返回API请求响应时间',
                           labelnames=['url', 'group', 'alias'], registry=REGISTRY)

HEADERS = {
    'Referer': 'http://www.baidu.com',
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                  'Chrome/93.0.3683.86 Safari/537.36',
}


import time
import yaml
import os
import concurrent.futures
import requests

NEW_URLS = []


def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs)
        print('共耗时约 {:.2f} 秒'.format(time.time() - start))
        return res

    return wrapper


HEADERS = {
    'Accept': '*/*',
    'Accept-Language': 'en-US,en;q=0.8',
    'Cache-Control': 'max-age=0',
    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 '
                  'Safari/537.36',
    'Connection': 'keep-alive',
    'Referer': 'http://www.baidu.com/'
}


def get_urls_from_yaml() -> list:
    """
    获取config目录所有yaml配置文件,并解析成如下格式
    [{'group':'g1','alias':'a1'},{'group':'g2','alias':'a2'}]
    :return:
    """
    # 获取当前目录
    config_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "rules")
    all_url_dict = []

    for file_name in os.listdir(config_dir):
        with open(os.path.join(config_dir, file_name), encoding='utf-8') as yaml_file:
            url_list = yaml.safe_load(yaml_file)
            for group, aliases in url_list.items():
                for alias, url_info in aliases.items():
                    url_dict = {'group': group, 'alias': alias, 'url': url_info.get("url"), 'status_code': 0,
                                'response_time': 0}
                    all_url_dict.append(url_dict)

    return all_url_dict


def load_url(url, timeout):
    try:
        # 获取重定向次数
        response = requests.get(url, headers=HEADERS)
        urls = get_urls_from_yaml()

        res = requests.get(url, timeout=timeout, stream=True)
        print(f"状态码：{res.status_code}, url：{res.url}, 请求时间:{res.elapsed.total_seconds()}, 跳转次数:{len(response.history)}\n")
    except requests.exceptions.SSLError as ex:
        print(ex)
    except requests.exceptions.ReadTimeout as ex:
        print(ex)
    except requests.exceptions.ConnectionError as ex:
        print(ex)
    # 使用url对url信息组进行匹配，匹配上则插入状态码、请求时间、重定向次数，证书剩余可用时间，http版本，TLS版本、DNS耗时
    # for u in urls:

    # group = {'group': u.get('group'), 'alias': u.get('alias'), 'url': url, 'status_code': res.status_code,
    #        'response_time': res.elapsed.total_seconds()}
    # NEW_URLS.append(group)


@timer
def main():
    with concurrent.futures.ThreadPoolExecutor(max_workers=200) as executor:
        urls = get_urls_from_yaml()
        future_to_url = (executor.submit(load_url, url.get('url'), 3) for url in urls)
        for future in concurrent.futures.as_completed(future_to_url):
            future.result()


main()


@app.route('/')
def hello():
    return '<a href="https://gitee.com/yunwe/api-exporter">api-exporter项目说明</a>'


@app.route('/metrics')
def metrics():
    """
    返回指定格式的值，例如：API{request_time="0.12",status_code="405",url="www.jianshu.com"} 1.0
    :return:
    """

    # api_msg_list = Rest.get_api()
    # for api in api_msg_list:
    #     gauge_status_code.labels(api['url'], api['alias'], api['type'], api['match'], api['group']).set(
    #         api['status_code'])
    #     gauge_request_time.labels(api['url'], api['group'], api['alias']).set(api['request_time'])
    #
    # return Response(generate_latest(registry), mimetype='text/plain')


if __name__ == '__main__':
    asyncio.run(main())
    server = pywsgi.WSGIServer(('0.0.0.0', 8000), app)
    server.serve_forever()
